/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author ALICIA
 */
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Random;
import java.util.Vector;
import org.encog.*;
import org.encog.engine.network.activation.ActivationSigmoid;
import org.encog.ml.data.MLData;
import org.encog.ml.data.MLDataPair;
import org.encog.neural.data.NeuralData;
import org.encog.neural.data.NeuralDataPair;
import org.encog.neural.data.NeuralDataSet;
import org.encog.neural.data.basic.BasicNeuralDataSet;
import org.encog.neural.networks.BasicNetwork;
import org.encog.neural.networks.layers.BasicLayer;
import org.encog.neural.networks.training.Train;
import org.encog.neural.networks.training.lma.LevenbergMarquardtTraining;
import org.encog.neural.networks.training.propagation.resilient.ResilientPropagation;


public class pennModel {

private static Double a=0.85;
private static Integer ANUAL=1;
public StdStats st;
public Vector<Double> newdata;
public Vector<Double> logdata;
public Vector<Double> input2NN;
public Vector<Vector<Double> > targetoutput;
// solamente para prueba 
public Vector<Double> test;

    public Vector<Double> getLogdata() {
        return logdata;
    }

    public void setLogdata(Vector<Double> logdata) {
        this.logdata = logdata;
    }

    public Vector<Double> getNewdata() {
        return newdata;
    }

    public void setNewdata(Vector<Double> newdata) {
        this.newdata = newdata;
    }

    public StdStats getSt() {
        return st;
    }

    public void setSt(StdStats st) {
        this.st = st;
    }

    public Vector<Double> getInput2NN() {
        return input2NN;
    }

    public void setInput2NN(Vector<Double> input2NN) {
        this.input2NN = input2NN;
    }

    public Vector<Double> getTest() {
        return test;
    }

    public void setTest(Vector<Double> test) {
        this.test = test;
    }
    

public pennModel() {
    st= new StdStats();
    newdata = new Vector<Double>();
    logdata = new Vector<Double>();
    input2NN = new Vector<Double>();
    test = new Vector<Double>();
   // targetoutput= new Vector<Vector<Double>>();
    }


public Double Skewness(Vector<Double> x)
{

    Double sum=0.0;

    Double meanx=st.mean(x);
    Double stdx=st.stddev(x);
    for(Double xf:x)
    {
        sum+=Math.pow(xf-meanx,3.0);
    }

    return sum/((x.size()-1)*Math.pow(stdx, 3.0));

    //return 0.0;
}
public void NN()
{
     double XOR_INPUT[][] = {
  { 0.0, 0.0 },
  { 1.0, 0.0 },
  { 0.0, 1.0 },
  { 1.0, 1.0 } };
    double XOR_IDEAL[][] = {
  { 0.0 },
  { 1.0 },
  { 1.0 },
  { 0.0 } };

    NeuralDataSet traininSet = new BasicNeuralDataSet(XOR_INPUT, XOR_IDEAL);
    BasicNetwork network= new BasicNetwork();
    
    
    network.addLayer(new BasicLayer(new ActivationSigmoid(),true,2));
    network.addLayer(new BasicLayer(new ActivationSigmoid(),true,4));
    network.addLayer(new BasicLayer(new ActivationSigmoid(),true,1));
    network.getStructure().finalizeStructure();
    network.reset();

    LevenbergMarquardtTraining tt= new LevenbergMarquardtTraining(network,traininSet);

    int epoch=1;

    do {

  tt.iteration();
  System.out.println("Epoch #" + epoch +
                     " Error:" + tt.getError());
  epoch++;

} while(tt.getError() > 0.01);

System.out.println("Neural Network Results:");

for(MLDataPair pair : traininSet){

  MLData output=network.compute(pair.getInput());
  System.out.println(pair.getInput().getData(0) +
         "," + pair.getInput().getData(1)  +
         ", actual=" + output.getData(0) +
         ",ideal=" + pair.getIdeal().getData(0));

}

}
/*
 *  tomasAndFiering : parte no deterministica pero sòlo con un atraso 
 *  input : data historica
 */
public Double tomasAndFiering(Vector<Double> inp,Integer mes)
{ // solamente cuando newlog estè lleno
    Vector<Double> xlogstd=new Vector<Double>();
    Vector<Double> ylogstd= new Vector<Double>();
    //se obitienen datos pertenecientes a cada mes de la data historica
    for(int i=mes;i<inp.size();i+=12)
    {   xlogstd.add(logdata.get(i));
        ylogstd.add(logdata.get(i-1));
     }
    System.out.println(xlogstd);
    System.out.println(ylogstd);
    Random ran = new Random();
    Double evt=ran.nextGaussian();
    Double svt=st.stddev(xlogstd);

   Double ccor=st.corrPer(xlogstd, ylogstd);
    System.out.println(ccor);
    
    return evt*svt*Math.sqrt(1-(ccor*ccor));




}
public void transLogone()
{
    
}
/*
 *  transLog : trnaformacion logaritmica de datos historicos
 *  input : data historica
 */
public void transLog(Vector<Double> input)
{

    //mes inical se considera 1
    newdata=(Vector<Double>) input.clone();
    logdata=(Vector<Double>) input.clone();
    Vector<Double> xi=new Vector<Double>();
    Vector<Double> XLOG=new Vector<Double>();
    Vector<Double> Xstda= new Vector<Double>();
    Double meanxlog=0.0;
    Double stdxlog=0.0;
    for (int i=0;i<12;i++)
    {
        
        for(int mes=i;mes<input.size();mes+=12){//System.out.println(mes);
        xi.add(input.get(mes));}
     /*coeficiente de asimetria skewness
     * a : constante
     */
    Double g=Skewness(xi);
    System.out.println(g);
    Double ximean=st.mean(xi);
    Double ct=a/Math.pow(g, 2.0);
        for(Double df:xi){   XLOG.add(Math.log10(df+(ct*ximean))); }//data normalizada
         meanxlog=st.mean(XLOG);
         stdxlog=st.stddev(XLOG);
        for(Double dfxlog:XLOG){Xstda.add((dfxlog-meanxlog)/stdxlog);}

   
    Integer count2=0;
    for(int j=i;j<input.size();j+=12)
    {
            newdata.set(j,Xstda.get(count2));
            logdata.set(j,XLOG.get(count2));
            count2++;
    }

     XLOG.clear();
    Xstda.clear();
    xi.clear();
    }
    
    
    


}
// estimacion anual 
public void splitData(Vector<Double> inp,Integer year)
    {
            input2NN=(Vector<Double>) inp.clone();
            for (int y=inp.size()-(12*year);y<input2NN.size();y++ ){test.add(inp.get(y));}
            input2NN.setSize(inp.size()-(12*year));
            
            //System.out.println(test);
    }
public void mapMinMax(Vector<Double> inp,Double min,Double max)
{

    Double xmin=st.min(inp);
    Double xmax=st.max(inp);
    for(int i=0;i<inp.size();i++){
      inp.setElementAt((max-min)*(inp.get(i)-xmin)/(xmax-xmin) + min,i);
    
    }
    for (Double dat:inp){
       // System.out.println(dat+"\n");
        }
    //System.out.println(inp);
}
public void reversemapMinMax(Vector<Double> inp,Double min,Double max)
{
    Double xmin=st.min(inp);
    Double xmax=st.max(inp);
    for(int i=0;i<inp.size();i++){
      inp.setElementAt((max-min)*(inp.get(i)-xmin)/(xmax-xmin) + min,i);
      
    }
    for (Double dat:inp){
        //System.out.println(dat+"\n");
        }
}
public void nomNN(Vector<Double> inp,Integer lags)
{
    targetoutput= new Vector<Vector<Double>>(lags);
    Vector<Double> ve;
   for(int i=0;i<lags;i++)
   {
       ve= new Vector<Double>(inp.size());
       
       for(int l=0;l<inp.size();l++){ve.add(0.0);}
    for(int y=i+1;y<inp.size();y++)
    {        
        ve.setElementAt(inp.get(y),y-1);

    }
    targetoutput.add(ve);
    
    
    //ve.clear();

   }
  // for (Vector<Double>  dat:targetoutput){
    //for(Double as:dat){
       // System.out.println(as+"\n");
        //System.out.println(dat.size());
        //System.out.println(inp.size());
    //}
  // }
    
}


public static void main(String[] args) throws FileNotFoundException, IOException
    {
        readClassSerie fil= new readClassSerie();
       //fil.readToVectFaltante("C:/Users/ALICIA/Favorites/Documents/NetBeansProjects/JavaApplication1/src/DataTest/2003/af.txt");
        fil.readToVect("C:/Users/ALICIA/Favorites/Documents/NetBeansProjects/JavaApplication1/src/caudalPanieData.txt");
        //System.out.println(fil.getSerie().size());
        //System.out.println(fil.getSerie());
        pennModel pen = new pennModel();
        // crea la red neuronal
        pen.NN();
        // tranformada la data historica
        
        pen.splitData(fil.getSerie(), ANUAL);
        
        pen.transLog(pen.getInput2NN());
        
        //prueba ruido blanco
       // System.out.println(pen.tomasAndFiering(pen.getNewdata(),9));
        //pen.splitData(fil.getSerie(), ANUAL);

        //data para la red ver propiedades de las funciones de activacion
        Vector<Double> tmp=(Vector<Double>) pen.getNewdata().clone();
        
        pen.mapMinMax(pen.getNewdata(), -1.0, 1.0);
        
        System.out.println(tmp);
        for (Double dat:tmp){
        System.out.println(dat+"\n");
        }
        System.out.println(pen.getNewdata());
        System.out.println(pen.getSt().min(tmp));
        System.out.println(pen.getSt().max(tmp));
        pen.mapMinMax(pen.getNewdata(), pen.getSt().min(tmp), pen.getSt().max(tmp));
        for (Double dat:pen.getNewdata()){
        //System.out.println(dat+"\n");
        }
        //System.out.println(pen.getNewdata());
        //procesamos data historica con N retrasos
        pen.nomNN(pen.getNewdata(),1);
        

    }


}

